unit U_ColorSpace_Fusion;
interface
uses
  SysUtils, StrUtils, TypInfo;
type
  T_Nucleotid = 'A'..'T';
const
  DNA_letter: array[0..3, 0..3] of integer = ((0, 1, 2, 3), (1, 0, 3, 2), (2, 3, 0, 1), (3, 2, 1, 0)); //matrix of SOLiD read translation
  Valid_combination: array[0..3, 0..3] of integer = ((1, 2, 3, 4), (2, 1, 4, 3), (3, 4, 1, 2), (4, 3, 2, 1)); //matrix of diColor group polymorphism
  nt_code: array[0..3] of char = ('A', 'C', 'G', 'T');
  nt_code_lower: array[0..3] of char = ('a', 'c', 'g', 't');
function RawColorToRawNucleotid(raw_color_code: string; length_raw: integer): string;
function RawNucleotidToRawColor(raw_nucleotid: string): string;
function NucleotidToColorIndex(nt_letter: char): integer;
function NucleotidReverse(nt_letter: char): char;

implementation

//------------------------------------------------------------------------------
//Detect the single mismatch

function isNotSingleMismatch(color1_read, color2_read, color1_ref,
  color2_ref: integer): boolean;
begin
  if ((color1_read = color1_ref) and (color2_read = color2_ref))
    or ((color1_read <> color1_ref) and (color2_read <> color2_ref)) then
    result := TRUE
  else
    result := FALSE;
end;

//------------------------------------------------------------------------------
//Detect the valid combination of two adjacent mismatches --> SNPs

function isTrueSNP(color1_read, color2_read, color1_ref,
  color2_ref: integer): boolean;
var
  group_read: integer;
  group_ref: integer;
begin
  group_read := Valid_combination[color2_read][color1_read];
  group_ref := Valid_combination[color2_ref][color1_ref];
  //With SOLiD ColorSpace, some mismatch are invalid --> Not SNP
  if (color1_read <> color1_ref) and (color2_read <> color2_ref) then
  begin
    if group_read = group_ref then
      result := TRUE //TRUE SNP
    else
      result := FALSE; //Sequencing error
  end;
end;

//------------------------------------------------------------------------------
//Read Color code --> Nucleotid Raw
function RawColorToRawNucleotid(raw_color_code: string; length_raw: integer): string;
var
  j: integer;
  color1: integer; //Color at t
  color2: integer; //Color at t+1
  length_dna: integer; //Use to find the position of the final nucleotid
  translation: integer;
  dna:string;
begin
  dna:='';
  //Si chaine de caractere non vide traduire code couleur en sequence nucleotidique
  if AnsiCompareStr(raw_color_code[1], '') <> 0 then
  begin
    //Check if the first item is 'T'
    if (raw_color_code[1] = 'T') then
    begin
      //For each item of the read
      //the raw of color has 36 colors to obtain a dna of 35 nucleotids
      for j := 2 to length_raw + 1 do
      begin
        color2 := ord(raw_color_code[j]) - ord('0');
        //Extract Position of translated read
        length_dna := Length(dna);
        //Change the first T into the rank code associated
        if length_dna = 0 then
        begin
          color1 := 3;
        end;
        //Use the translation matrix to extract the rank of the nucleotid
        translation := DNA_letter[color2][color1];
        //Add the nucleotid to the translated read
        dna := dna + nt_code[translation];
        //For the next iteration, use the rank of the final translated nucleotid
        color1 := translation;
      end;
      //Stock the translate sequence
      result := dna;
    end;
  end;
end;

//------------------------------------------------------------------------------

function RawNucleotidToRawColor(raw_nucleotid: string): string;
var
  nt_letter1: char;
  nt_letter2: char;
  Raw_Seq_color:string;
  color1: integer;
  color2: integer;
  i: integer;
begin
  nt_letter1 := 'N';
  nt_letter2 := 'N';
  i := 1;
  Raw_Seq_color := '';

  while i <= Length(raw_nucleotid) do
  begin
    if i + 1 <= Length(raw_nucleotid) then
    begin
      //Recup the letters
      nt_letter1 := raw_nucleotid[i];
      nt_letter2 := raw_nucleotid[i+1];

      //Translate the nucleotid into index
      color1 := NucleotidToColorIndex(nt_letter1);
      color2 := NucleotidToColorIndex(nt_letter2);

      //Use the two index to translate the ref into color sequence
      Raw_Seq_color := Raw_Seq_color + IntToStr(DNA_letter[color1][color2]);
    end;
    Inc(i, 1);
  end;
  result := Raw_Seq_color;
end;

//------------------------------------------------------------------------------

function NucleotidToColorIndex(nt_letter: char): integer;
var
  index_color: integer;
begin
  case AnsiIndexStr(nt_letter, ['A', 'C', 'G', 'T', 'N', '.', 'X']) of
    0: index_color := 0;
    1: index_color := 1;
    2: index_color := 2;
    3: index_color := 3;
    4: index_color := 4;
    5: index_color := 4;
    6: index_color := 4;
  end;
  result := index_color;
end;

//------------------------------------------------------------------------------

function NucleotidReverse(nt_letter: char): char;
var
  reverse_nt: T_Nucleotid;
begin
  reverse_nt := 'N';
  case nt_letter of
    'A': reverse_nt := 'T';
    'C': reverse_nt := 'G';
    'G': reverse_nt := 'C';
    'T': reverse_nt := 'A';
    'N': reverse_nt := 'N';
  end;
  Result := reverse_nt;
end;

end.

